﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data.SQLite;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WebLog.Db.SqlLogHelpers
{
    /// <summary>
    /// 监听sql的路径 的操作类
    /// </summary>
    public static class LogSqlPathConfigHelper
    {
        //如果有 控制器等等的
        //那就禁用
        //控制器的这种属于不可删除的
        //每次都执行一次比对 把不存在的记录删除 把不存在的数据库的新增

        //手动加的可以删除/禁用

        //后期这边可以重构为 编辑立刻生效 然后数据库更改随后完成
        static object logPathLock = new object();
        static List<logPaths> LogPaths
        {
            get => _logPaths = _logPaths ?? GetAndLoadLogPaths();
        }
        static List<logPaths> _logPaths = null;
        /// <summary>
        /// 添加监听的请求路径 
        /// 例如（/api/ProductionPlan/GetProductionPlanList）
        /// </summary>
        /// <param name="paths"></param>
        public static void DeffAndChangeLogPaths(IEnumerable<string> paths)
        {
            if (paths == null || paths.Count() == 0) return;
            if(!WebLogHelper.StatusWait.VerifyStatus(WebLogStatus.TimerNotRun, () => DeffAndChangeLogPaths(paths))) return;
            var dbPaths = LogPaths;
            var dbs = dbPaths.Select(e => e.Path);
            deleteLogPaths(true, dbs.Except(paths).ToArray());//数据库有 传递的没有
            SetAndAddLogPaths(true, true, paths.Except(dbs).ToArray());// 传递的有 数据库没有
        }
        #region 查询配置
        internal static object Searchs(SearchLogPathsInputDto searchLogInputDto)
        {
            string commandStr = @"select * from logPaths where 1=1 ";
            string orderStr = "";
            SQLiteParameter[] sQLiteParameters = null;
            bool isSearchAll = true;
            if (searchLogInputDto != null)
            {
                sQLiteParameters = new SQLiteParameter[5];
                int j = 0;
                if (searchLogInputDto.CurrentPageIndex.HasValue && searchLogInputDto.PageSize.HasValue)
                {
                    isSearchAll = false;
                    orderStr += @"limit @Skip,@Take";
                    //页码处理
                    int Skip = searchLogInputDto.CurrentPageIndex.Value * searchLogInputDto.PageSize.Value
                        , Take = searchLogInputDto.PageSize.Value;
                    sQLiteParameters[j++] = new SQLiteParameter("Skip", Skip);
                    sQLiteParameters[j++] = new SQLiteParameter("Take", Take);
                }
                if (!searchLogInputDto.Path.IsNullEmpty())
                {
                    isSearchAll = false;
                    commandStr += @"and (@Path='%%' or Path like @Path)";
                    sQLiteParameters[j++] = new SQLiteParameter("Path", "%" + (searchLogInputDto.Path ?? "") + "%");
                }
                if (searchLogInputDto.IsEnable.HasValue)
                {
                    isSearchAll = false;
                    commandStr += @"and (@IsEnable is null or @IsEnable='' or IsEnable=@IsEnable)";
                    sQLiteParameters[j++] = new SQLiteParameter("IsEnable", searchLogInputDto.IsEnable);
                }
                if (searchLogInputDto.IsAuto.HasValue)
                {
                    isSearchAll = false;
                    commandStr += @"and (@IsAuto is null or @IsAuto='' or IsAuto=@IsAuto)";
                    sQLiteParameters[j++] = new SQLiteParameter("IsAuto", searchLogInputDto.IsAuto);
                }
            }
            var dt = Comm.sqliteHelper.GetDataTable(commandStr + orderStr, null, sQLiteParameters: sQLiteParameters);
            var totalStr = Comm.sqliteHelper.GetDataTable(commandStr.Replace("select *", "select count(*)"), sQLiteParameters: sQLiteParameters).Rows[0][0].ToString();
            if (isSearchAll)//查询所有时
            {
                var dtStr = JsonConvert.SerializeObject(dt);
                _logPaths = JsonConvert.DeserializeObject<List<logPaths>>(dtStr);//更新数据
            }
            return new { total = int.Parse(totalStr), rows = dt };
        }
        #endregion 查询配置
        internal static List<logPaths> GetAndLoadLogPaths(bool isReload = false, params string[] paths)
        {
            lock (logPathLock)
            {
                //默认使用缓存
                if (_logPaths != null && !isReload) return _logPaths;
                Searchs(null);
            }
            //返回配置集合
            return _logPaths;
        }
        internal static string DeleteLogPaths(params string[] paths) => deleteLogPaths(false, paths);
        static string deleteLogPaths(bool isAuto, params string[] paths)
        {
            if (paths == null || paths.Length < 1) return "参数有误！";
            string msg = "";
            bool flag = true;
            lock (logPathLock)
            {
                var finds = LogPaths.FindAll(l => l.IsAuto == isAuto && paths.Contains(l.Path));//待删除数据
                if (finds.Count == 0)
                {
                    Comm.sysLogHelper.AppendSysLog(msg = "删除了自动配置，失败了！");
                    return msg;
                }
                var pms = new List<SQLiteParameter> { new SQLiteParameter("IsAuto", isAuto) };
                SQLiteParameter sQLiteParameter;
                string commandStr = "";
                for (int j = 0; j < finds.Count; j++)
                {
                    pms.Add(sQLiteParameter = new SQLiteParameter("p" + pms.Count, finds[j].Path));
                    commandStr += string.Format("delete from logPaths where IsAuto=@IsAuto and path=@{0};", sQLiteParameter.ParameterName);
                }
                var i = Comm.sqliteHelper.ExecuteNonQuery(commandStr
                    , sQLiteParameters: pms.ToArray());
                if (i < 1) flag = false;//失败了
                else LogPaths.RemoveAll(l => finds.Contains(l));//修改数据
                Comm.sysLogHelper.AppendSysLog(msg = string.Format("{0}删除了监听配置:{1}.{2}", (flag ? "成功" : "失败")
                    , string.Join(',', paths), (flag && i < paths.Length)? "可能其中包括了自动产生的配置，未删除成功！": ""));
            }
            return msg;
        }
        internal static string SetAndAddLogPaths(bool isEnable, params string[] paths) => SetAndAddLogPaths(isEnable, false, paths);
        /// <summary>
        /// 判断请求的路径是否需要写日志
        /// </summary>
        /// <param name="ReqPath">请求的路径</param>
        /// <returns></returns>
        internal static bool IsWriteLog(string ReqPath)
            => LogPaths.Any(l => l != null && l.IsEnable
            && (l.Path.Equals(ReqPath) || ReqPath.Contains(l.Path)));
        static string SetAndAddLogPaths(bool isEnable, bool isAuto = false, params string[] paths)
        {
            string msg = "";
            if (paths == null || paths.Length < 1) return msg = "参数不对";
            if (paths.Any(p => p == null || !p.Contains("/") || p.Length < 8)) return msg = "参数不对,每个元素必须包含'/',且长度大于8";
            lock (logPathLock)
            {
                //db操作确保成功
                var dbs = LogPaths.FindAll(l => paths.Contains(l.Path));
                dbs.ForEach(l => l.IsEnable = isEnable);//修改数据
                var dbpaths = dbs.Select(e => e.Path);
                var needAdds = paths.Except(dbpaths);//数据库没有的
                var needUpdates = dbs.FindAll(d => dbpaths.Except(needAdds).Contains(d.Path));//数据库已有的 需要更新
                if (!needAdds.Any() && !needUpdates.Any()) return msg = "修改成功";//没数据

                string commandStr = "", insertsStr = "", updateStr = "";
                var sQLiteParameters = new List<SQLiteParameter>();
                sQLiteParameters.AddRange(
                    new[] { new SQLiteParameter("IsAuto", isAuto), new SQLiteParameter("IsEnable", isEnable) });
                SQLiteParameter sQLiteParameterPath;
                foreach (var item in needAdds)
                {
                    LogPaths.Add(new logPaths { IsAuto = isAuto, Path = item, IsEnable = isEnable });
                    sQLiteParameterPath = new SQLiteParameter("p" + sQLiteParameters.Count, item);
                    insertsStr += string.Format("(@IsAuto,@IsEnable,@{0}),", sQLiteParameterPath.ParameterName);
                    sQLiteParameters.Add(sQLiteParameterPath);
                }
                //新增
                if (needAdds.Count() > 0)
                    commandStr += string.Format("INSERT INTO logPaths(IsAuto, IsEnable, Path) VALUES {0};", insertsStr.Substring(0, insertsStr.Length - 1));
                
                foreach (var item in needUpdates)
                    item.IsEnable = isEnable;
                //编辑
                if (needUpdates.Count > 0)
                {
                    for (int j = 0; j < needUpdates.Count; j++)
                    {
                        sQLiteParameters.Add(sQLiteParameterPath = new SQLiteParameter("p" + sQLiteParameters.Count, needUpdates[j].Path));
                        updateStr += string.Format(@"update logPaths set IsEnable=@IsEnable
                            where path =@{0};", sQLiteParameterPath.ParameterName);
                    }
                    commandStr += updateStr;
                }
                var i = Comm.sqliteHelper.ExecuteNonQuery(commandStr, sQLiteParameters: sQLiteParameters.ToArray());
                if (paths.Length > 0)
                    Comm.sysLogHelper.AppendSysLog(msg = string.Format("{0}-{1}了监听配置:{2}", i > 0? "成功": "失败", (isEnable ? "启用" : "禁用"), string.Join(',', paths)));
                return msg;
            }
        }
    }
}
